// debugger 需要下面两个
import chroma from "chroma-js";
import { Matrix } from "game-algorithm";
import { Application, Container, Graphics } from "pixi.js";
import { alpha0 } from "../Constant";
import { nextReDrawTick } from "./DrawEngine";

//** debugger用 */
const getDifferentColor = (number: number) => chroma.random();
let _debugTime = true;
const _debugFlash = (tile: Tile) => {
    tile.g
        .beginFill(
            chroma(getDifferentColor(tile.x + tile.y)).num(),
            _debugTime ? 0.2 : 0.4
        )
        .drawRect(0, 0, tile.tileSize, tile.tileSize);
    _debugTime = !_debugTime;
};

export class Tile {
    g = new Graphics();
    init: { x: number; y: number };
    constructor(
        public x: number,
        public y: number,
        public tileSize: number,
        drawLock = true
    ) {
        this.init = { x: x * tileSize, y: y * tileSize };
        this.g
            .beginFill(0, alpha0)
            .drawRect(0, 0, tileSize, tileSize)
            .endFill()
            .position.set(this.init.x, this.init.y);

        // _debugFlash(this);
        this.drawLock = drawLock;
    }
    /** 绘制锁 */
    get drawLock() {
        return !this.g.visible;
    }
    set drawLock(val: boolean) {
        this.g.visible = !val;
    }

    /** 重新绘制 Tile */
    reDraw(m: Matrix<[number, number]>) {
        if (this.drawLock) {
            return;
        }
        this.g.clear();
        //! debugger 专用代码
        // _debugFlash(this);
        const { x: X, y: Y } = this.init;
        new Matrix({
            height: this.tileSize,
            width: this.tileSize,
            voidValue: (x, y) => {
                let data = m.get(x + X, y + Y);
                if (data) {
                    let [color, alpha] = data;
                    if (alpha <= 0) alpha = alpha0;

                    this.g.beginFill(color, alpha / 255).drawRect(x, y, 1, 1);
                }
            },
        });
        this.g.endFill();
    }
    mount(c: Container) {
        c.addChild(this.g);
        return this;
    }
}
/** 整个数据地图，将会挂载到一个 PIXI 对象上 */
export class TileMap {
    /** 瞬时绘制数组 */
    dataMatrix;
    private tileMatrix;
    constructor(
        public width: number,
        public height: number,
        public tileSize: number,
        public container: Graphics
    ) {
        // 数目需要添加多一个防止画面不够
        const ySize = Math.ceil(height / tileSize);
        const xSize = Math.ceil(width / tileSize);

        this.dataMatrix = new Matrix<[number, number]>({
            height: this.height,
            width: this.width,
            voidValue: () => {
                return [0, 0];
            },
        });
        this.tileMatrix = new Matrix({
            height: ySize,
            width: xSize,
            voidValue: (x, y) => {
                return new Tile(x, y, tileSize, false).mount(container);
            },
        });
    }

    /** 重新进行图像可视范围绘制 */
    autoRender(app: Application) {
        // const { height, width } = app.screen;
        // const lt = this.container.toLocal({ x: 0, y: 0 });
        // const rb = this.container.toLocal({ x: width, y: height });
        // const x_min = Math.floor(lt.x / this.tileSize);
        // const y_min = Math.floor(lt.y / this.tileSize);
        // const x_max = Math.ceil(rb.x / this.tileSize);
        // const y_max = Math.ceil(rb.y / this.tileSize);
        // this.tileMatrix.$forEach((i) => {
        //     if (i.x >= x_min && i.x <= x_max && i.y >= y_min && i.y <= y_max) {
        //         i.drawLock = false;
        //     } else if (i.drawLock === false) {
        //         i.drawLock = true;
        //         i.reDraw(this.dataMatrix);
        //     }
        // });
    }

    /** 时间段内缓存的需要重绘的 Tile */
    private reDrawCache = new Set<Tile>();

    /** x,y 为数据坐标，改变数据的内容 */
    changeMatrix(x: number, y: number, value: [number, number]) {
        this.dataMatrix.set(x, y, value);
        const X = Math.floor(x / this.tileSize);
        const Y = Math.floor(y / this.tileSize);
        const tile = this.tileMatrix.get(X, Y);
        if (tile && !tile.drawLock) {
            this.reDrawCache.add(tile);
        }
    }
    /** 重绘，分区块进行渲染，没有变化不会进行渲染 */
    drawMatrix() {
        this.reDrawCache.forEach((i) => i.reDraw(this.dataMatrix));
        this.reDrawCache.clear();
    }
}
